package com.mtw.bbs.auth.service;


import com.mtw.bbs.auth.pojo.PayloadData;
import com.mtw.bbs.auth.utils.JwtTokenUtil;
import com.mtw.bbs.common.core.constant.ServiceConstant;
import com.mtw.bbs.common.core.enums.ResultCode;
import com.mtw.bbs.common.core.exception.AuthException;
import com.mtw.bbs.common.core.exception.BaseException;
import com.mtw.bbs.common.core.vo.Result;
import com.mtw.bbs.userAdmin.pojo.dto.UserDto;
import com.mtw.bbs.userAdmin.feign.ResourceClient;
import com.mtw.bbs.userAdmin.feign.UserClient;
import com.mtw.bbs.userAdmin.pojo.vo.ResourceVo;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.CollectionUtils;

import java.util.Collection;
import java.util.Map;


@RequiredArgsConstructor
@Service
@Slf4j
public class AuthenticationServiceImpl implements AuthenticationService {

    private final AntPathMatcher antPathMatcher = new AntPathMatcher();
    private final ResourceClient resourceClient;
    private final JwtTokenUtil jwtTokenUtil;
    private final UserClient userClient;

    @Override
    public boolean logout(HttpServletRequest request) {
        return false;
    }

    /**
     * 校验token
     * @param token
     * token正确，返回用户信息
     */
    @Override
    @SneakyThrows
    public UserDto authentication(String token) {

        log.debug("正在校验的token是:{}", token);
        return validateAuth(token);
    }


    /**
     * @param param 访问的url,method,token
     * @return 有权限true, 无权限或全局资源中未找到请求url返回否
     */
    @Override
    @SneakyThrows
    public UserDto authentication(Map<String, Object> param) {
        return validateAuth((String)param.get("token"),(String)param.get("url"),(String) param.get("method"));
    }


    /**
     * 验证token合法性
     * @return  授权用户信息
     */
    @SneakyThrows
    private UserDto validateAuth(String token){

        boolean validate = jwtTokenUtil.validateJwtToken(token);
        if (!validate){
            throw new AuthException(ResultCode.AUTH_ERROR.getCode(),"无效token");
        }
        PayloadData payloadData = jwtTokenUtil.getPayload(token);
        Result<UserDto> userDtoResult = userClient.getUserInfoByUsername(payloadData.getUsername());
        if (userDtoResult.isFail()){
            throw new BaseException(userDtoResult.getCode(),userDtoResult.getMesg());
        }
        UserDto userDto = userDtoResult.getData();
        if (userDto == null){
            throw new AuthException(ResultCode.AUTH_ERROR.getCode(),"用户信息不存在");
        }

        if (ServiceConstant.STATUS_DISABLE == userDto.getStatus()){
            throw new AuthException("账号已禁用");
        }
        return userDto;
    }


    /**
     * 验证是否拥有权限
     * @param token
     * @param url
     * @param method
     * @return
     */
    @SneakyThrows
    private UserDto validateAuth(String token,String url,String method){

        boolean validate = jwtTokenUtil.validateJwtToken(token);
        if (!validate){
            throw new AuthException(ResultCode.AUTH_ERROR.getCode(),"无效token");
        }
        PayloadData payloadData = jwtTokenUtil.getPayload(token);

        // 获取用户信息及权限
        Result<UserDto> userDtoResult = userClient.loadUserByUserName(payloadData.getUsername());
        if (userDtoResult.isFail()){
            throw new BaseException(userDtoResult.getCode(),userDtoResult.getMesg());
        }
        UserDto userDto = userDtoResult.getData();
        if (userDto == null){
            throw new AuthException(ResultCode.AUTH_ERROR.getCode(),"用户信息不存在");
        }

        if (ServiceConstant.STATUS_DISABLE == userDto.getStatus()){
            throw new AuthException("账号已禁用");
        }

        if (CollectionUtils.isEmpty(userDto.getResource())){
            throw new AuthException("无访问权限");
        }

        //用户拥有权限资源 与 url要求的资源进行对比
        boolean match = isMatch(url, method, userDto.getResource());
        if (!match){
            throw new AuthException("无访问权限");
        }

        return userDto;
    }

    /**
     * url对应资源与用户拥有资源进行匹配
     *
     */
    private boolean isMatch(String url, String method, Collection<ResourceVo> resources) {

        return resources.stream().anyMatch(p -> {
            String resourceMethod = p.getMethod();
            String resourceUrl = p.getUrl();
           return method.equalsIgnoreCase(resourceMethod) && antPathMatcher.match(resourceUrl, url);
        });
    }

}
